//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Tokens;
using System.ServiceModel;
using System.ServiceModel.Security.Tokens;

namespace Shp.Security.BrokeredReceiver
{
    /// <summary>
    /// Class that helps to create a SAML token
    /// </summary>
	static class SamlTokenCreator
	{
        /// <summary>
        /// Creates a SAML Token with the input parameters
        /// </summary>
        /// <param name="stsName">Name of the STS issuing the SAML Token</param>
        /// <param name="proofToken">Associated Proof Token</param>
        /// <param name="issuerToken">Associated Issuer Token</param>
        /// <param name="proofKeyEncryptionToken">Token to encrypt the proof key with</param>
        /// <param name="samlConditions">The Saml Conditions to be used in the construction of the SAML Token</param>
        /// <param name="samlAttributes">The Saml Attributes to be used in the construction of the SAML Token</param>
        /// <returns>A SAML Token</returns>
        static public SamlSecurityToken CreateSamlToken(string stsName,
                                                        BinarySecretSecurityToken proofToken,
                                                        SecurityToken issuerToken,
                                                        SecurityToken proofKeyEncryptionToken,
                                                        SamlConditions samlConditions,
                                                        IEnumerable<SamlAttribute> samlAttributes)
		{
            SecurityKeyIdentifierClause identifierClause = issuerToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            SecurityKeyIdentifier issuerKeyIdentifier = new SecurityKeyIdentifier(identifierClause);
            byte[] wrappedKey = proofKeyEncryptionToken.SecurityKeys[0].EncryptKey(SecurityAlgorithms.RsaOaepKeyWrap, proofToken.GetKeyBytes());
            SecurityKeyIdentifierClause encryptingTokenClause = proofKeyEncryptionToken.CreateKeyIdentifierClause<X509ThumbprintKeyIdentifierClause>();
            EncryptedKeyIdentifierClause encryptedKeyClause = new EncryptedKeyIdentifierClause(wrappedKey, SecurityAlgorithms.RsaOaepKeyWrap, new SecurityKeyIdentifier(encryptingTokenClause) );
            SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(encryptedKeyClause);

			List<string> confirmationMethods = new List<string>(1);
			confirmationMethods.Add(SamlConstants.HolderOfKey);

			SamlSubject samlSubject = new SamlSubject(null,
													  null,
													  null,
													  confirmationMethods,
													  null,
                                                      proofKeyIdentifier);

			SamlAttributeStatement samlAttributeStatement = new SamlAttributeStatement(samlSubject, samlAttributes);
			List<SamlStatement> samlSubjectStatements = new List<SamlStatement>();
			samlSubjectStatements.Add(samlAttributeStatement);

            SigningCredentials signingCredentials = new SigningCredentials(issuerToken.SecurityKeys[0],
                                                                           SecurityAlgorithms.RsaSha1Signature,
                                                                           SecurityAlgorithms.Sha1Digest,
                                                                           issuerKeyIdentifier);

			SamlAssertion samlAssertion = new SamlAssertion("_" + Guid.NewGuid().ToString(),
							                                stsName,
							                                DateTime.UtcNow,
							                                samlConditions,
							                                new SamlAdvice(),
							                                samlSubjectStatements
						                                	);
			samlAssertion.SigningCredentials = signingCredentials;

			return new SamlSecurityToken(samlAssertion);
		}
	}
}
